﻿using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.Logic;
using LFloatMath.Math;
using NetProtocol.POD;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class BattleCommandView_StartPart : BaseBattleCommandView<BattleCommand_StartPart>
    {
        private SkillPartConfig partConfig;
        protected override EBattleUpdateType commandType => EBattleUpdateType.StartPart;

#if UNITY_EDITOR
        public override string ToString()
        {
            return base.ToString() + $"[{(HasTimeline() ? partConfig.timeline : "-")}] - [{command.partGUID}]";
        }
#endif

        protected override void OnInitialize(BattleCommand_StartPart rCommand, int nExecuterID)
        {
            base.OnInitialize(rCommand, nExecuterID);
            var rUnit = BattleManager.Instance.ctrl.data.GetUnit(nExecuterID);
            if (rUnit != null)
            {
                var rConfig = SkillFactory.GetConfig(command.skillID);
                for (var i = 0; i < rConfig.parts.Count; i++)
                    if (rConfig.parts[i].guid == command.partGUID)
                    {
                        partConfig = rConfig.parts[i];
                        return;
                    }
            }
        }

        private bool HasTimeline()
        {
            return partConfig != null && !string.IsNullOrEmpty(partConfig.timeline);
        }

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;
            await base.OnPlayUpdate(unit);
            if (HasTimeline())
            {
                var rTimelineComp = unit.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent);
                rTimelineComp.curPartTargetList = command.targetGUID;
                while (rTimelineComp.curState != BattleTimelineComponent.ETimelineState.WaitForPlay) await UniTask.Yield();
                rTimelineComp.PlayTimeline(partConfig.timeline, command).Forget();
            }
        }

        public override void OnReset()
        {
            base.OnReset();
            partConfig = null;
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_BuffChange : BaseBattleCommandView<BattleCommand_BuffChange>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.BuffChange;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;
            await base.OnPlayUpdate(unit);
            var rBuffComp = unit.GetComponent<BuffViewComponent>(ETComponentType.BuffViewComponent);
            if (rBuffComp == null) return;
            switch (command.triggerType)
            {
                case 0: // Start
                    rBuffComp.OnBuffAdd(command.buff);
                    break;
                case 1: // Remove
                    rBuffComp.OnBuffRemove(command.buff);
                    break;
                case 2: // Refresh
                    break;
                case 3: // Destroy
                    rBuffComp.OnDestroy(command.buff);
                    break;
            }
            MsgDispatcher.Broadcast(MsgEventType.BattleView_Buff, unit);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_AttrChange : BaseBattleCommandView<BattleCommand_AttrChange>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.AttrChange;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;

            await base.OnPlayUpdate(unit);
            var rAttr = unit.GetComponent<AttributeViewComponent>(ETComponentType.AttributeViewComponent);
            var rAttrType = (EAttributeType)command.attrType;
            var rAddType = (EAttributeAddType)command.addType;
            if (this.command.add)
                rAttr.Add(rAttrType, command.value, rAddType);
            else
                rAttr.Set(rAttrType, command.value, rAddType);

            MsgDispatcher.Broadcast(MsgEventType.BattleView_AttrChnage, unit, rAttrType);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_PosChange : BaseBattleCommandView<BattleCommand_PosChange>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.PosChange;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;
            await base.OnPlayUpdate(unit);
            if (this.command.path.Count > 0)
            {
                var rMoveComp = unit.GetComponent<BattleMoveComponent>(ETComponentType.BattleMoveComponent);
                await rMoveComp.AIMove(this.command.path);
                unit.pos = this.command.pos.ToLVector();
                unit.forward = this.command.forward.ToLVector();
            }
            else
            {
                unit.pos = command.pos.ToLVector();
                unit.forward = command.forward.ToLVector();
            }
            var rView = unit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
            await rView.SyncPos();
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }

#if UNITY_EDITOR
        public override string ToString()
        {
            return $"{base.ToString()}, pos[{command.pos.ToLVector()}],forward[{command.forward.ToLVector()}]";
        }
#endif
    }

    public class BattleCommandView_Dead : BaseBattleCommandView<BattleCommand_Dead>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.Dead;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;
            await base.OnPlayUpdate(unit);

            if (command.relive)
                unit.DeleteComponent(ETComponentType.DeadViewComponent);
            else
                unit.AddComponent<DeadViewComponent>(ETComponentType.DeadViewComponent);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_BuffDamage : BaseBattleCommandView<BattleCommand_BuffDamage>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.BuffDamage;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);

            // 冒字
            MsgDispatcher.Broadcast(MsgEventType.BattleView_TakeDamage, command.damage);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_BuffCure : BaseBattleCommandView<BattleCommand_BuffCure>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.BuffCure;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);

            // 冒字
            MsgDispatcher.Broadcast(MsgEventType.BattleView_TakeCure, command.cure);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_Shield : BaseBattleCommandView<BattleCommand_Shield>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.Shield;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);
            var rBuffComp = unit.GetComponent<BuffViewComponent>(ETComponentType.BuffViewComponent);
            rBuffComp.shield = command.shield;
            MsgDispatcher.Broadcast(MsgEventType.BattleView_Shield, unit);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_AddSkill : BaseBattleCommandView<BattleCommand_AddSkill>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.AddSkill;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;
            await base.OnPlayUpdate(unit);
            var rSkillViewComp = unit.GetComponent<SkillViewComponent>(ETComponentType.SkillViewComponent);
            if (command.add)
                rSkillViewComp.AddSkill(command.skillID);
            else
                rSkillViewComp.RemoveSkill(command.skillID);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_WeaknessPoint : BaseBattleCommandView<BattleCommand_WeaknessPoint>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.WeaknessPoint;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;
            await base.OnPlayUpdate(unit);
            unit.weaknessPoint = this.command.point;
            MsgDispatcher.Broadcast(MsgEventType.BattleView_WeaknessPoint, unit);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_CustomProperty : BaseBattleCommandView<BattleCommand_CustomProperty>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.CustomProperty;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null) return;
            await base.OnPlayUpdate(unit);
            var rCustom = unit.GetComponent<CustomPropertyViewComponent>(ETComponentType.CustomPropertyViewComponent);
            if (rCustom == null) return;

            if (this.command.key > 0)
            {
                var rValueType = (ETAnyType)this.command.valueType;
                var rKey = (ECustomProperty)this.command.key;
                switch (rValueType)
                {
                    case ETAnyType.Bool:
                        rCustom.SetProperty(rKey, TAnyHelper.GetAny<bool>(this.command.value), rValueType);
                        break;
                    case ETAnyType.LFloat:
                        rCustom.SetProperty(rKey, TAnyHelper.GetAny<float>(this.command.value), rValueType);
                        break;
                    case ETAnyType.Int32:
                        rCustom.SetProperty(rKey, TAnyHelper.GetAny<int>(this.command.value), rValueType);
                        break;
                    case ETAnyType.Int64:
                        rCustom.SetProperty(rKey, TAnyHelper.GetAny<long>(this.command.value), rValueType);
                        break;
                    case ETAnyType.String:
                        rCustom.SetProperty(rKey, TAnyHelper.GetAny<string>(this.command.value), rValueType);
                        break;
                    case ETAnyType.Vector2:
                        rCustom.SetProperty(rKey, TAnyHelper.GetAny<LVector2>(this.command.value), rValueType);
                        break;
                    case ETAnyType.Vector3:
                        rCustom.SetProperty(rKey, TAnyHelper.GetAny<LVector3>(this.command.value), rValueType);
                        break;
                }
            }
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_Charge : BaseBattleCommandView<BattleCommand_Charge>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.Charge;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);
            var rByteBuf = ThreadLocalTemporalByteBufPool.Alloc(64);
            rByteBuf.Replace(this.command.targetSelectConfig);
            var rTargetConfig = new TargetSelectConfig();
            rByteBuf.DeSerializeObject(ref rTargetConfig);
            var rIndicatorName = string.IsNullOrEmpty(this.command.chargePrefab) ? rTargetConfig.indicator : this.command.chargePrefab;
            if (string.IsNullOrEmpty(rTargetConfig.indicator))
            {
                rIndicatorName = TableCenter.skill.Get(this.command.curSkill)?.Indicator;
            }
            var rChargeComp = unit.GetComponent<ChargeViewComponent>(ETComponentType.ChargeViewComponent);
            rChargeComp?.StartCharge(rIndicatorName, rTargetConfig,
                this.command.pos.ToLVector().ToVector3XZ(), this.command.aspect.ToLVector().ToVector3XZ());
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_ChargeStop : BaseBattleCommandView<BattleCommand_ChargeStop>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.ChargeStop;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);
            var rChargeComp = unit.GetComponent<ChargeViewComponent>(ETComponentType.ChargeViewComponent);
            rChargeComp?.ChargeStop();
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_Morph : BaseBattleCommandView<BattleCommand_Morph>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.Morph;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);
            var rTimelineComp = unit.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent);
            rTimelineComp.Stop();
            var rViewComp = unit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
            if (this.command.active)
                await rViewComp.Morph(this.command.resName, this.command.entityType);
            else
                await rViewComp.RemoveMorph(this.command.resName);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_PermitCast : BaseBattleCommandView<BattleCommand_PermitCast>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.PermitCast;
        private int skillID => this.command.skillID;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null)
            {
                return;
            }
            await base.OnPlayUpdate(unit);
            // 刷新按键
            var rSkillViewComp = unit.GetComponent<SkillViewComponent>(ETComponentType.SkillViewComponent);
            if (this.skillID == 0)
            {
                rSkillViewComp.ResetSkillCastList();
            }
            else
            {
                var rSkillConfig = TableCenter.skill.Get(this.skillID);
                var nSkillIndex = rSkillConfig.SkillSlot - 1;
                for (int i = 0; i < rSkillViewComp.skills.Length; i++)
                {
                    rSkillViewComp.skills[i] = i == nSkillIndex ? this.skillID : 0;
                }
            }
            var rViewComp = unit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
            await rViewComp.InControl();
            var rQueueCtrl = BattleManager.Instance.ctrl.queueCtrl;
            BattleManager.Instance.ctrl.orderCtrl.RefreshSkill(rSkillViewComp);
            BattleManager.Instance.ctrl.sceneCtrl.CameraOnSelectCharacter(rViewComp);
            // 弹窗说话
            if (rQueueCtrl.TryGetDialog(unit.GUID, 1))
            {
                rViewComp.ShowHeadLightDialog(unit.property.dialog, 0, 3).Forget();
            }
            // 等待释放
            while (true)
            {
                // 有后续数据开始释放 由逻辑层控制，不存在插入的情况了
                if (rQueueCtrl.TryPeek(out _))
                {
                    break;
                }
                await UniTask.Yield();
            }
            rViewComp.OutControl();
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_CastSkill : BaseBattleCommandView<BattleCommand_CastSkill>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.CastSkill;
        public int skillID => this.command.skillID;
        public int aiMoveType;

#if UNITY_EDITOR
        public override string ToString()
        {
            return $"{base.ToString()}, aiMoveType[{this.aiMoveType}], skillID[{this.skillID}]";
        }
#endif

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            // 在服务器完全自主释放技能时候，会出现没有castparam的情况，直接抛弃继续播后面的就行
            await base.OnPlayUpdate(unit);
            if (unit == null)
            {
                return;
            }
            var rTurnCtrl = BattleManager.Instance.ctrl.turnCtrl;
            var rViewComp = unit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
            var bCast = this.skillID != 0;
            if (bCast)
            {
                var rSkillTableConfig = TableCenter.skill.Get(this.skillID);
                var rSkillType = (ESkillType)(1 << rSkillTableConfig.SkillType);

                // 怪物释放大招时冒泡，仅首次播
                if (rTurnCtrl.turnFirstPart && unit.unitType == EUnitType.Monster && !string.IsNullOrEmpty(unit.property.dialog) &&
                    rTurnCtrl.current != null && rTurnCtrl.current == unit)
                {
                    if (rSkillType == ESkillType.BigSkill)
                    {
                        rViewComp.ShowHeadLightDialog(unit.property.dialog, 0, 3).Forget();
                    }
                }

                // 宠物技能在这里变身
                if (rSkillType == ESkillType.PetSkill)
                {
                    var rPetComponent = unit.GetComponent<PetViewComponent>(ETComponentType.PetViewComponent);
                    await rPetComponent.ShowPet();
                }
            }

            rTurnCtrl.turnFirstPart = false;
            var rTimelineComp = unit.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent);
            rTimelineComp.curPartTargetPos = this.command.targetPos.ToLVector();

            rViewComp.OutControl();
            var rMoveComp = unit.GetComponent<BattleMoveComponent>(ETComponentType.BattleMoveComponent);
            rMoveComp.aiMoveType = this.aiMoveType;
        }

        public override void OnReset()
        {
            base.OnReset();
            this.aiMoveType = 0;
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_CastSkillComplete : BaseBattleCommandView<BattleCommand_CastSkillComplete>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.CastSkillComplete;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);

            var rQueueCtrl = BattleManager.Instance.ctrl.queueCtrl;
            var rTimelineComp = unit.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent);
            while (rTimelineComp.curState == BattleTimelineComponent.ETimelineState.Playing || rQueueCtrl.InWaitingBulletHit())
            {
                await UniTask.Yield();
            }
            if (!rQueueCtrl.TryPeek(out var rCmd) || rCmd.localCommand)
            {
                BattleManager.Instance.SkillComplete();
            }
            var rMoveComp = unit.GetComponent<BattleMoveComponent>(ETComponentType.BattleMoveComponent);
            rMoveComp.aiMoveType = 0;

            // 宠物技能在这里变回
            var rPetComponent = unit.GetComponent<PetViewComponent>(ETComponentType.PetViewComponent);
            await rPetComponent.HidePet();
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_Round : BaseBattleCommandView<BattleCommand_Round>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.Round;
        private int roundNum => this.command.roundNum;
        private List<int> turnQueue => this.command.turnQueue;
        private bool isEnd => this.command.isEnd;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);

            // 先等一下用来区分两回合
            await UniTask.Delay(BattleConst.TurnStartWaitAfterCamera, cancellationToken: this.cancel.Token);

            BattleManager.Instance.ctrl.data.roundNum = this.roundNum;
            if (!this.isEnd)
            {
                var rUnits = BattleManager.Instance.ctrl.data.units;
                for (int i = 0; i < rUnits.Count; i++)
                {
                    rUnits[i]?.GetComponent<SkillViewComponent>(ETComponentType.SkillViewComponent)?.OnRoundStart();
                }
            }

            MsgDispatcher.Broadcast(MsgEventType.BattleView_Round, this.roundNum);
            var rTurnCtrl = BattleManager.Instance.ctrl.turnCtrl;
            rTurnCtrl.SyncAfterTurn(this.turnQueue, true);
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }

        public override string ToString()
        {
            return $"{(this.isEnd ? "回合结束" : "回合开始")}, 当前回合数: {this.roundNum}";
        }
    }

    public class BattleCommandView_Turn : BaseBattleCommandView<BattleCommand_Turn>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.Turn;
        private List<int> turnQueue => this.command.turnQueue;

        protected override void OnInitialize(BattleCommand_Turn rCommand, int nExecuterID)
        {
            base.OnInitialize(rCommand, nExecuterID);
        }

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);

            var rTurnCtrl = BattleManager.Instance.ctrl.turnCtrl;
            // 换人等0.5
            if (rTurnCtrl.current != null && rTurnCtrl.current != unit)
            {
                await UniTask.Delay(BattleConst.TurnStartWait, cancellationToken: this.cancel.Token);
            }
            // 切镜头
            BattleManager.Instance.ctrl.sceneCtrl.CameraOnSelectCharacter(unit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent));
            // 再等0.5
            await UniTask.Delay(BattleConst.TurnStartWaitAfterCamera, cancellationToken: this.cancel.Token);

            rTurnCtrl.SetCurrent(this.executerID);
            rTurnCtrl.SyncAfterTurn(this.turnQueue, false);
            MsgDispatcher.Broadcast(MsgEventType.BattleView_Turn, this.executerID);

            // 英雄在血量低于35时候弹窗说话
            if (unit.unitType == EUnitType.Hero && !string.IsNullOrEmpty(unit.property.dialog))
            {
                var rAttrComp = unit.GetComponent<AttributeViewComponent>(ETComponentType.AttributeViewComponent);
                var rCurHpRate = rAttrComp.Get(EAttributeType.Hp) / Math.Max(rAttrComp.Get(EAttributeType.MaxHp), 1);
                if (rCurHpRate.ToFloat() <= 0.35f)
                {
                    BattleManager.Instance.ctrl.queueCtrl.AddDialog(unit.GUID, 1);
                }
            }
            rTurnCtrl.turnFirstPart = true;
        }

        public override void Free()
        {
            this.turnQueue.Clear();
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_NextWave : BaseBattleCommandView<BattleCommand_NextWave>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.NextWave;
        private BattleTeamViewPOD nextTeam => this.command.team;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);
            await BattleManager.Instance.ctrl.OnNextWave(this.nextTeam);
            BattleManager.Instance.ctrl.data.roundNum = BattleConst.StartRound; // 重置回合数
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_RemoveUnit : BaseBattleCommandView<BattleCommand_RemoveUnit>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.RemoveUnit;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);
            if (unit != null)
            {
                BattleManager.Instance.ctrl.data.RemoveUnit(unit);
            }
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }

    public class BattleCommandView_Substitute : BaseBattleCommandView<BattleCommand_Substitute>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.Substitute;
        private BattleUnitViewPOD subUnit => this.command.subUnit;
        private int teamIndex => this.command.teamIndex;

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);

            var rBattleData = BattleManager.Instance.ctrl.data;
            var rSubUnit = UnitViewFactory.CreateBattleUnitView(this.subUnit, this.teamIndex);
            rBattleData.AddUnit(rSubUnit);

            await rSubUnit.InitializeView();

            var rComp = rSubUnit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
            var rDeadComp = unit.GetComponent<DeadViewComponent>(ETComponentType.DeadViewComponent);
            while (rDeadComp is { realDead: false })
            {
                await UniTask.Yield();
            }
            // 切镜头
            BattleManager.Instance.ctrl.sceneCtrl.CameraOnSelectCharacter(rComp);

            await UniTask.Delay(BattleConst.SubstituteBefore, cancellationToken: this.cancel.Token);
            rComp.Enable();
            await UniTask.Delay(BattleConst.SubstituteWait, cancellationToken: this.cancel.Token);
        }
    }
}